#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
For example::
>>> query = 'fentanil'
>>> from str_analyzer import StrAnalyzer
>>> sa = StrAnalyzer()
>>> result = sa.detect_object(query)
>>> print result
('drug', ('Fentanil', 'Fentanyl (also known as fentanil, brand names Sublimaze,[3] \
Actiq, Durogesic, Duragesic, Fentora, Matrifen, Haldid, Onsolis,[4] Instanyl,[5] \
Abstral,[6] Lazanda[7] and others[8]) is a potent, synthetic opioid analgesic with \
a rapid onset and short duration of action.'), \
[('Fentanil 24 hours', '4 mg prol-rel. capsules', 'fen100677d.pdf')], None)
"""

from wiki_indexes.wiki_index_bacteria import bacteria_wiki_index as bacterias
from wiki_indexes.wiki_index_cell import cell_wiki_index as cells
from wiki_indexes.wiki_index_desease import desease_wiki_index as deseases
from wiki_indexes.wiki_index_drug import drug_wiki_index as drugs
from wiki_indexes.wiki_index_enzime import enzime_wiki_index as enzimes
from wiki_indexes.wiki_index_fungi import fungi_wiki_index as fungis
from wiki_indexes.wiki_index_human_part import human_part_wiki_index  as human_parts
from wiki_indexes.wiki_index_measure import measure_wiki_index as measures
from wiki_indexes.wiki_index_operation import operation_wiki_index as operations
from wiki_indexes.wiki_index_science import science_wiki_index as sciences
from wiki_indexes.wiki_index_virus import virus_wiki_index as viruses
from bda_indexes.bda_index_drug import drug_bda_index as bda
from drugscom_indexes.drugs_com_index import drugs_com_index as drugs_com
import string
import os
import time


__author__ = 'gogo'

__version__ = '0.0.1'


class StrAnalyzer(object):
    """
    class for object detection and wiki/bda link extraction
    """
    def __init__(self, stop_words=None):
        if stop_words is None:
            from dict.eng_stop_words import stop_words
            self.stop_words = stop_words

    # table = string.maketrans("", "")
    # exclude = set(string.punctuation)

    def __clear_punctuation(self, user_string):
        """
        clear punctuation and convert to lower case
        :param user_string:
        """
        # return user_string.translate(self.table, string.punctuation)
        # return ''.join(ch for ch in user_string if ch not in self.exclude)
        for c in string.punctuation:
            user_string = user_string.replace(c, " ")

        return user_string.lower()

    def __remove_stop_words(self, my_string):
        not_stop_words = []
        if my_string is None:
            return None
        for word in my_string.split():
            if word not in self.stop_words:
                not_stop_words.append(word)

        return not_stop_words

    # TODO da gi otdelq v otdelen klas za indexksirane
    # def get_bda_link(self, drug, ltype=1):
    #     fl = drug.strip()[0].upper()
    #     links = []
    #     with open('bda' + str(ltype) + '/' + fl + '.txt') as f:
    #         for line in f:
    #             part = line.strip().split('||')
    #             if drug.strip().lower() in part[0].lower().strip():
    #                 links.append((part[0].strip(), part[1].strip(), part[2].strip()))
    #         return links
    #
    # TODO da gi otedlq w otelen klas za postroqvane na indeksite
    # def __get_wiki_link(self, word, word_type=None):
    #     if word_type == 'virus':
    #         'grep -q ^' + word.capitalize() + '$' + ' /home/gogo/PycharmProjects/se_test/wikippages'
    #     else:
    #         grep = 'grep -q ^' + word.capitalize() + '$' + ' /home/gogo/PycharmProjects/se_test/wikippages'
    #     r = os.system(grep)
    #     if r == 0:
    #         return word.capitalize()
    #     else:
    #         return None

    def __get_drugs_com(self, word):
        """

        :param word:
        :return:
        """
        if word in drugs_com:
            return word
        else:
            return None

    def __search_drug(self, word1, word2=None):
        """

        :param word1:
        :param word2:
        :return:
        """
        data = self.__calc_data('drug', word1)
        new_link = []
        if data[2]:
            for d in data[2]:
                if word2 in d[0].lower() or word2 in d[1].lower():
                    new_link.append(d)
        if new_link:
            return data[0], data[1], new_link, data[3]
        else:
            return data

    def __check_word_type(self, word):
        """

        :param word:
        :return:
        """
        if word in drugs:
            wtype = 'drug'
        elif word in viruses:
            wtype = 'virus'
        elif word in deseases:
            wtype = 'desease'
        elif word in bacterias:
            wtype = 'bacteria'
        elif word in cells:
            wtype = 'cell'
        elif word in enzimes:
            wtype = 'enzime'
        elif word in fungis:
            wtype = 'fungi'
        elif word in sciences:
            wtype = 'science'
        elif word in human_parts:
            wtype = 'human_part'
        elif word in measures:
            wtype = 'measure'
        elif word in operations:
            wtype = 'operation'
        else:
            wtype = None
        return wtype

    def __get_bda_index(self, word):
        """

        :param word:
        :return:
        """
        if word in bda:
            return bda[word]
        else:
            return None

    def __get_wiki_desc(self, word, dtype='short'):
        try:
            with open(dtype+'_desc/'+word+'.txt') as f:
                return f.read()
        except:
            return None

    def __get_wiki_index(self, wtype ,word):

        def bacteria(w):
            if w in bacterias:
                return bacterias[w]
            else:
                return None

        def drug(w):
            if w in drugs:
                return drugs[w]
            else:
                return None

        def cell(w):
            if w in cells:
                return cells[w]
            else:
                return None

        def desease(w):
            if w in deseases:
                return deseases[w]
            else:
                return None

        def enzime(w):
            if w in enzimes:
                return enzimes[w]
            else:
                return None

        def fungi(w):
            if w in fungis:
                return fungis[w]
            else:
                return None

        def human_part(w):
            if w in human_parts:
                return human_parts[w]
            else:
                return None

        def measure(w):
            if w in measures:
                return measures[w]
            else:
                return None

        def operation(w):
            if w in operations:
                return operations[w]
            else:
                return None

        def scince(w):
            if w in sciences:
                return sciences[w]
            else:
                return None

        def virus(w):
            if w in viruses:
                return viruses[w]
            else:
                return None

        return {
            'bacteria': bacteria(word),
            'cell': cell(word),
            'drug': drug(word),
            'desease': desease(word),
            'enzime': enzime(word),
            'fungi': fungi(word),
            'science': scince(word),
            'human_part': human_part(word),
            'measure': measure(word),
            'operation': operation(word),
            'virus': virus(word)
        }[wtype], self.__get_wiki_desc(word)

    def __calc_data(self, wtype, word):
        """

        :param wtype:
        :param word:
        :return:
        """
        if wtype is None:
            return None
        elif wtype == 'drug':
            return 'drug', self.__get_wiki_index('drug', word), self.__get_bda_index(word), self.__get_drugs_com(word)
        else:
            return wtype, self.__get_wiki_index(wtype, word)

    def detect_object(self, user_string):
        """

        :param user_string:
        :return:
        """
        my_string = self.__clear_punctuation(user_string)
        bag_words = self.__remove_stop_words(my_string)
        # print bag_words
        if len(bag_words) == 0:
            # print 0
            return None
        elif len(bag_words) == 1:
            wtype = self.__check_word_type(bag_words[0])
            return self.__calc_data(wtype, bag_words[0])
                #return bag_words
        elif len(bag_words) == 2:
            wtype0 = self.__check_word_type(bag_words[0])
            wtype1 = self.__check_word_type(bag_words[1])
            if wtype0 is None and wtype1 is None:
                return None
            elif wtype0 == 'drug' and wtype1 is None:
                return self.__search_drug(bag_words[0], bag_words[1])
            elif wtype1 == 'drug' and wtype0 is None:
                return self.__search_drug(bag_words[1], bag_words[0])
            elif wtype0 is not None and wtype0 is not None:
                return [self.__calc_data(wtype0, bag_words[0]), self.__calc_data(wtype1, bag_words[1])]
            elif wtype0 != 'drug' and wtype1 is None:
                return [self.__calc_data(wtype0, bag_words[0]), None]
            elif wtype1 != 'drug' and wtype0 is None:
                return [None, self.__calc_data(wtype1, bag_words[1])]


if __name__ == '__main__':
    import doctest
    doctest.testmod()